Previously we were using TF card boot, which corresponds to the hardware interface SD0. Now to change the boot method and boot the system from eMMC, some modifications need to be made to the previous configuration:
In Vivado's block design, enable SD1 (eMMC is mounted on the SD1 interface on the core board):
Continue with the subsequent operations: "Generate Bitstream" --> "Export Hardware" --> Export the .xsa file.
Copy the .xsa file from Windows to the virtual machine via a shared folder, then copy the xsa file from the shared folder to the working directory:
Run the Petalinux environment in the working directory and perform related configuration: use the command:
xspetapetalinux-config --get-hw-description=.#Import new xsa and complete configuration
Configure uboot to qspi-flash, and both image and rootfs to eMMC:
Partition the qspi-flash:
xxxxxxxxxxpetalinux-config --get-hw-description=.Subsystem AUTO Hardware Settings-->Flash Settings-->The filesystem is on mmcblk1p2.
xxxxxxxxxxpetalinux-config --get-hw-description=.Image Packaging Configuration--->
Select ps7_sd_1. ps7_sd_1 corresponds to eMMC.
xxxxxxxxxxpetalinux-config --get-hw-description=.Subsystem AUTO Hardware Settings-->SD/SDIO Settings-->
xxxxxxxxxxpetalinux-config --get-hw-description=.petalinux-config -> u-boot configuration ->u-boot script configuration -> QSPI/SPI image offsets# Here Zynq uses image.ub (which contains kernel and dtb, image.ub is a fit image)xxxxxxxxxxpetalinux-config -c u-boot ARM architecture -> (0xFE0000) Boot script offset# 0xFE0000 corresponds to the starting address of bootsrc in qspi flashCompile and package
xxxxxxxxxxpetalinux-buildpetalinux-package --boot --fsbl ./images/linux/zynq_fsbl.elf --u-boot --fpga --force#At this point, boot.src/BOOT.bin/image.ub/roofs.tar.gz are generatedFirst, configure the development board to SD card boot mode, connect the network cable, power on, and create an image folder in its /home/root directory. Then, via FTP, copy the image.ub and roofs.tar.gz generated on the virtual machine to the image directory. At this point, the kernel image and filesystem for eMMC mode are temporarily stored on the TF card.
Copy the generated BOOT.bin/image.ub/zynq_fsbl.elf/boot.src files to the Windows environment. Set the development board to JTAG mode, power on, and use Vitis's program flash tool to burn the BOOT.bin/image.ub/zynq_fsbl.elf/boot.src files into the qspi-flash (refer to the previous qspi-flash partition information for specific burn addresses):
(1) Burn BOOT.bin: select BOOT.bin as the image file, fill in offset 0x0000000.
(2) Burn image.ub: first rename image.ub to image.ub.bin; then select image.ub.bin as the image file, fill in offset 0x5A0000.
(3) Burn boot.src: first rename boot.src to boot.src.bin; then select boot.src.bin as the image file, fill in offset 0xFE0000:
After uboot starts, it will load the boot.src script. In this script, it will perform corresponding reading, loading, and bootm based on the current boot mode.
Format and partition the eMMC
Power off, set the boot mode to SD card, insert the TF card into the slot, power on to enter the Linux system on the TF card.
Delete existing eMMC partitions and repartition
xxxxxxxxxx# Check if current eMMC partitions have mount pointsmount# If mounted, unmount firstumount /dev/mmcblk1p1umount /dev/mmcblk1p2# Format eMMC#fdisk /dev/mmcblk1Delete partitions
Input "p" to see the current partition situation.
Input "d" to delete a partition. If there are multiple partitions, input "d" multiple times.
Input "p" again to see the current partition situation.
Create the first partition
Input "n" to create a partition. Input "p" (primary partition), then input "1" (partition number), "2048" (first sector), "+1G" (allocate 1GB to the first partition) or directly specify the last sector.
Input "t" to set the partition type, input "b" to set the type to "W95 FAT32".
Input "p" again will display the current partition status, including the end sector number of the current partition (corresponding to EndLBA).
Create the second partition
Use the "n" command, input "p" (primary partition), then input "2", and leave the remaining space for the second partition by just pressing enter.
If the first sector is not incremented based on the end sector number of the first partition when creating the second partition, enter the EndLBA value of the previous partition + 1.
Check the partition table
Input "p" to check if there are two partitions; if everything is correct, input "w" to write the partition table to the TF card.
Format the partitions
xxxxxxxxxx# Format the first partition as FAT32mkfs.vfat -F 32 /dev/mmcblk1p1# Format the second partition as EXT4mkfs.ext4 /dev/mmcblk1p2 Copy and extract the image.ub and roofs.tar.gz for eMMC boot from the TF card to the eMMC partitions
xxxxxxxxxx# Create two folders as mount points for the two eMMC partitionsmkdir /media/mmcblk1p1mkdir /media/mmcblk1p2# Mount /dev/mmcblk1p1 to /media/mmcblk1p1mount /dev/mmcblk1p1 /media/mmcblk1p1# Mount /dev/mmcblk1p2 to /mnt/mmcblk1p2mount /dev/mmcblk1p2 /media/mmcblk1p2# Copy image.ub to /dev/mmcblk1p1cp /home/root/image/image.ub /media/mmcblk1p1sync
# Extract rootfs.tar.gz to /dev/mmcblk1p2tar -xzf /home/root/image/rootfs.tar.gz -C /media/mmcblk1p2syncNote: Since the image is loaded from qspi-flash, it is also acceptable not to copy image.ub to the first partition.
Power off, set the boot mode to spi-flash mode, and power on. At this time, uboot and the kernel will be loaded from qspi-flash, and the filesystem will be loaded from eMMC.
After U-Boot starts, it loads the boot.src script. This script performs corresponding read, load, and bootm operations based on the current boot mode.
The following is the content of the default boot.src file:
xxxxxxxxxx# Traverse boot mode (JTAG/QSPI/MMC/NAND)for boot_target in ${boot_targets};do echo "Trying to load boot images from ${boot_target}" if test "${boot_target}" = "jtag" ; then bootm 0x00200000 0x04000000 0x00100000 fi if test "${boot_target}" = "mmc0" || test "${boot_target}" = "mmc1" ; then # If booting from mmc, check whether there is a uEnv.txt file # under mmc (current petalinux does not contain this file) if test -e ${devtype} ${devnum}:${distro_bootpart} /uEnv.txt; then # load uEnv.txt fatload ${devtype} ${devnum}:${distro_bootpart} 0x02080000 uEnv.txt; echo "Importing environment(uEnv.txt) from ${boot_target}..." env import -t 0x02080000 $filesize if test -n $uenvcmd; then echo "Running uenvcmd ..."; run uenvcmd; fi fi # If the mmc contains the image.ub file if test -e ${devtype} ${devnum}:${distro_bootpart} /image.ub; then # load image.ub to 0x10000000 fatload ${devtype} ${devnum}:${distro_bootpart} 0x10000000 image.ub; # boot from 0x10000000 bootm 0x10000000; fi # If you start from mmc, the following code will not be executed normally. # If mmc contains uImage file and system.dtb file if test -e ${devtype} ${devnum}:${distro_bootpart} /uImage; then fatload ${devtype} ${devnum}:${distro_bootpart} 0x00200000 uImage;; fi if test -e ${devtype} ${devnum}:${distro_bootpart} /system.dtb; then fatload ${devtype} ${devnum}:${distro_bootpart} 0x00100000 system.dtb; fi # If mmc contains ramdisk.cpio.gz.u-boot file if test -e ${devtype} ${devnum}:${distro_bootpart} /ramdisk.cpio.gz.u-boot && test "${skip_tinyramdisk}" != "yes"; then fatload ${devtype} ${devnum}:${distro_bootpart} 0x04000000 ramdisk.cpio.gz.u-boot; bootm 0x00200000 0x04000000 0x00100000 fi if test -e ${devtype} ${devnum}:${distro_bootpart} /rootfs.cpio.gz.u-boot && test "${skip_ramdisk}" != "yes"; then fatload ${devtype} ${devnum}:${distro_bootpart} 0x04000000 rootfs.cpio.gz.u-boot; bootm 0x00200000 0x04000000 0x00100000 fi bootm 0x00200000 - 0x00100000 fi # If booted from qspi if test "${boot_target}" = "xspi0" || test "${boot_target}" = "qspi" || test "${boot_target}" = "qspi0"; then sf probe 0 0 0; # Load the contents of qspi offset address 0x5A0000, length 0xA40000 to 0x10000000 # 0x5A0000 and 0xA40000 correspond to the image.ub of the qspi space division above sf read 0x10000000 0x5A0000 0xA40000 # Boot from 0x10000000 bootm 0x10000000; echo "Booting using Fit image failed"
sf read 0x00200000 0x1000000 0x500000 sf read 0x04000000 0x1580000 0xA00000 bootm 0x00200000 0x04000000 0x00100000; echo "Booting using Separate images failed" fi if test "${boot_target}" = "nand" || test "${boot_target}" = "nand0"; then nand info; nand read 0x10000000 0x1080000 0x6400000 bootm 0x10000000; echo "Booting using Fit image failed"
nand read 0x00200000 0x1000000 0x3200000 nand read 0x04000000 0x4600000 0x3200000 bootm 0x00200000 0x04000000 0x00100000; echo "Booting using Separate images failed" fidoneIf the boot mode is qspi, both U-Boot and the image will be loaded from qspi flash.
If the boot mode is mmc0 or mmc1, both U-Boot and the image will be loaded from mmc.
Based on the previous analysis of the boot.src file, if you want to load U-Boot from qspi flash and load the image from mmc, you need to modify the boot.src file.
Because the boot.src file itself has CRC verification, directly modifying the boot.src content will cause boot.src verification to fail, thus preventing the kernel from starting.
boot.src is generated from the template components/yocto/layers/meta-xilinx/meta-xilinx-bsp/recipes-bsp/u-boot/u-boot-zynq-scr/boot.cmd.generic, so you can modify the boot.cmd.generic file.
However, the boot.cmd.generic file may be automatically overwritten during petalinux-config.
A reasonable modification method is to add a u-boot-zynq-scr.bbappend file and a u-boot-zynq-scr folder in project-spec/meta-user/recipes-bsp/uboot/.
Patching U-Boot boot script in Petalinux 2021.1
qspi-flash can still be partitioned according to the above steps; including petalinux-config and U-Boot config;
Create u-boot-zynq-scr.bbappend file and u-boot-zynq-scr folder in project-spec/meta-user/recipes-bsp/uboot/
xxxxxxxxxx# u-boot-zynq-scr.bbappend file content as follows:
FILESEXTRAPATHS_prepend := "${THISDIR}/u-boot-zynq-scr:"
SRC_URI += "file://boot.cmd.generic"Copy the components/yocto/layers/meta-xilinx/meta-xilinx-bsp/recipes-bsp/u-boot/u-boot-zynq-scr/boot.cmd.generic file to the u-boot-zynq-scr folder, then modify this file:
x
# This is a boot script for U-Boot# Generate boot.scr:# mkimage -c none -A arm -T script -d boot.cmd.default boot.scr#################@@PRE_BOOTENV@@
for boot_target in ${boot_targets};do echo "Trying to load boot images from ${boot_target}" if test "${boot_target}" = "jtag" ; then @@KERNEL_BOOTCMD@@ @@KERNEL_LOAD_ADDRESS@@ @@RAMDISK_IMAGE_ADDRESS@@ @@DEVICETREE_ADDRESS@@ fi if test "${boot_target}" = "mmc0" || test "${boot_target}" = "mmc1" ; then if test -e ${devtype} ${devnum}:${distro_bootpart} /@@UENV_TEXTFILE@@; then fatload ${devtype} ${devnum}:${distro_bootpart} @@UENV_MMC_LOAD_ADDRESS@@ @@UENV_TEXTFILE@@; echo "Importing environment(@@UENV_TEXTFILE@@) from ${boot_target}..." env import -t @@UENV_MMC_LOAD_ADDRESS@@ $filesize if test -n $uenvcmd; then echo "Running uenvcmd ..."; run uenvcmd; fi fi if test -e ${devtype} ${devnum}:${distro_bootpart} /@@FIT_IMAGE@@; then fatload ${devtype} ${devnum}:${distro_bootpart} @@FIT_IMAGE_LOAD_ADDRESS@@ @@FIT_IMAGE@@; bootm @@FIT_IMAGE_LOAD_ADDRESS@@; fi if test -e ${devtype} ${devnum}:${distro_bootpart} /@@KERNEL_IMAGE@@; then fatload ${devtype} ${devnum}:${distro_bootpart} @@KERNEL_LOAD_ADDRESS@@ @@KERNEL_IMAGE@@;; fi if test -e ${devtype} ${devnum}:${distro_bootpart} /system.dtb; then fatload ${devtype} ${devnum}:${distro_bootpart} @@DEVICETREE_ADDRESS@@ system.dtb; fi if test -e ${devtype} ${devnum}:${distro_bootpart} /@@RAMDISK_IMAGE1@@ && test "${skip_tinyramdisk}" != "yes"; then fatload ${devtype} ${devnum}:${distro_bootpart} @@RAMDISK_IMAGE_ADDRESS@@ @@RAMDISK_IMAGE1@@; @@KERNEL_BOOTCMD@@ @@KERNEL_LOAD_ADDRESS@@ @@RAMDISK_IMAGE_ADDRESS@@ @@DEVICETREE_ADDRESS@@ fi if test -e ${devtype} ${devnum}:${distro_bootpart} /@@RAMDISK_IMAGE@@ && test "${skip_ramdisk}" != "yes"; then fatload ${devtype} ${devnum}:${distro_bootpart} @@RAMDISK_IMAGE_ADDRESS@@ @@RAMDISK_IMAGE@@; @@KERNEL_BOOTCMD@@ @@KERNEL_LOAD_ADDRESS@@ @@RAMDISK_IMAGE_ADDRESS@@ @@DEVICETREE_ADDRESS@@ fi @@KERNEL_BOOTCMD@@ @@KERNEL_LOAD_ADDRESS@@ - @@DEVICETREE_ADDRESS@@ fi if test "${boot_target}" = "xspi0" || test "${boot_target}" = "qspi" || test "${boot_target}" = "qspi0"; then ## This if is the added part: determine whether there is an image.ub file on mmc 1:${distro_bootpart} if test -e mmc 1:${distro_bootpart} /@@FIT_IMAGE@@; then echo "try to boot using mmc Fit image" # If so, load it to the FIT_IMAGE_LOAD_ADDRESS address (corresponding to 0x1000000) fatload mmc 1:${distro_bootpart} @@FIT_IMAGE_LOAD_ADDRESS@@ @@FIT_IMAGE@@; # Boot from FIT_IMAGE_LOAD_ADDRESS address bootm @@FIT_IMAGE_LOAD_ADDRESS@@; echo "Booting using mmc Fit image failed" fi # If there is no image.ub file on mmc, image.ub will still be loaded from qspi echo "try to boot using qspi Fit image" sf probe 0 0 0; sf read @@FIT_IMAGE_LOAD_ADDRESS@@ @@QSPI_FIT_IMAGE_OFFSET@@ @@QSPI_FIT_IMAGE_SIZE@@ bootm @@FIT_IMAGE_LOAD_ADDRESS@@; echo "Booting using Fit image failed"
sf read @@KERNEL_LOAD_ADDRESS@@ @@QSPI_KERNEL_OFFSET@@ @@QSPI_KERNEL_SIZE@@ sf read @@RAMDISK_IMAGE_ADDRESS@@ @@QSPI_RAMDISK_OFFSET@@ @@QSPI_RAMDISK_SIZE@@ @@KERNEL_BOOTCMD@@ @@KERNEL_LOAD_ADDRESS@@ @@RAMDISK_IMAGE_ADDRESS@@ @@DEVICETREE_ADDRESS@@; echo "Booting using Separate images failed" fi if test "${boot_target}" = "nand" || test "${boot_target}" = "nand0"; then nand info; nand read @@FIT_IMAGE_LOAD_ADDRESS@@ @@NAND_FIT_IMAGE_OFFSET@@ @@NAND_FIT_IMAGE_SIZE@@ bootm @@FIT_IMAGE_LOAD_ADDRESS@@; echo "Booting using Fit image failed"
nand read @@KERNEL_LOAD_ADDRESS@@ @@NAND_KERNEL_OFFSET@@ @@NAND_KERNEL_SIZE@@ nand read @@RAMDISK_IMAGE_ADDRESS@@ @@NAND_RAMDISK_OFFSET@@ @@NAND_RAMDISK_SIZE@@ @@KERNEL_BOOTCMD@@ @@KERNEL_LOAD_ADDRESS@@ @@RAMDISK_IMAGE_ADDRESS@@ @@DEVICETREE_ADDRESS@@; echo "Booting using Separate images failed" fidoneFollow the previous steps: After petalinux-build and packaging, copy BOOT.bin, boot.src, image.ub, and zynq_fsbl.elf to Windows, and use Vitis to burn them into qspi-flash; copy the image.ub file to the first partition of eMMC, and extract rootfs to the second partition of eMMC.